package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.article.domain.StrategyDays;
import cn.wolfcode.luowowo.article.service.IStrategyDetailService;
import cn.wolfcode.luowowo.search.domain.DestinationTemplate;
import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.DestinationSearchQuery;
import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IDestinationTemplateService;
import cn.wolfcode.luowowo.search.service.IStrategyTemplateService;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyTemplateServiceImpl implements IStrategyTemplateService {
    @Autowired
    private StrategyTemplateRepository repository;
    @Reference
    private IDestinationTemplateService destinationTemplateService;
    @Reference
    private IStrategyDetailService strategyDetailService;

    @Override
    public void save(StrategyTemplate template) {
        repository.save(template);
    }

    @Override
    public List<Map<String, Object>> queryThemeCommend() {
        List<Map<String,Object>> data = new ArrayList<>();
        //先查询出主题ID，主题名字，目的地数量存放在theme中
        List<StatisVO> list = this.queryStatisVoList("themeId", "themeName", "themeGroup");
        //通过themeId查询出目的地ID和name
        Map<String,Object> map = null;
        for (StatisVO vo : list) {
            map = new HashMap<>();
            List<StatisVO> vos = this.getDestByThemeId(vo.getId());
            map.put("theme",vo);
            map.put("dests",vos);
            data.add(map);
        }
        return data;
    }

    @Override
    public List<StatisVO> queryConditionChina() {
        return this.queryStatisVoList("provinceId","provinceName","provinceGroup");
    }

    @Override
    public List<StatisVO> queryConditionAbroads() {
        List<StatisVO> list = this.queryStatisVoList("countryId", "countryName", "countryGroup");
        Iterator<StatisVO> iterator = list.iterator();
        while (iterator.hasNext()) {
            StatisVO next = iterator.next();
            if(next.getName().equals("中国")){
                iterator.remove();
            }
        }
        return list;
    }

    @Override
    public List<StatisVO> queryConditionThemes() {
        return this.queryStatisVoList("themeId","themeName","themeGroup");
    }

    @Override
    public Page query(StrategySearchQuery qo) {
        TermQueryBuilder query = null;
        PageRequest pageRequest = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, qo.getOrderBy());
        if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_COUNTRY){
            query = QueryBuilders.termQuery("countryId",qo.getTypeValue());
        }else if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_PROVINCE){
            query = QueryBuilders.termQuery("provinceId",qo.getTypeValue());
        }else if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_THEME){
            query = QueryBuilders.termQuery("themeId",qo.getTypeValue());
        }
        if(query == null){
            return repository.findAll(pageRequest);
        }else{
            return repository.search(query,pageRequest);
        }
    }

    @Override
    public List<StrategyTemplate> findByDestName(String destName) {
        return repository.findByDestName(destName);
    }

    @Override
    public List<DestinationTemplate> queryDestination(DestinationSearchQuery qo) {
        int timeType = qo.getTimeType();
        List<Long> destIds = new ArrayList<>();
        List<Long> filterDays = new ArrayList<>();
        List<Long> list = new ArrayList<>();
        Iterable<StrategyTemplate> all = null;
        if(qo.getThemeId() != -1){
            all = repository.findByThemeId(qo.getThemeId());
        }else{
            all = repository.findAll();
        }
        for (StrategyTemplate template : all) {
            if(timeType != -1){
                Date createTime = template.getCreateTime();
                if(createTime != null){
                    if(timeType < 13){
                        //如果时间参数为月份
                        if(createTime.getMonth() == timeType){
                            destIds.add(template.getDestId());
                        }
                    }else{
                        //如果时间参数为节日
                        if(timeType == DestinationSearchQuery.NEW_YEARS_DAY){
                            if (createTime.getMonth() == 1){
                                destIds.add(template.getDestId());
                            }
                        }else if(timeType == DestinationSearchQuery.SPRING_FESTIVAL){
                            if (createTime.getMonth() == 1 || createTime.getMonth() == 2){
                                destIds.add(template.getDestId());
                            }
                        }else if (timeType == DestinationSearchQuery.MING_FESTIVAL){
                            if (createTime.getMonth() == 4){
                                destIds.add(template.getDestId());
                            }
                        }else if(timeType == DestinationSearchQuery.MAY_DAY){
                            if (createTime.getMonth() == 5){
                                destIds.add(template.getDestId());
                            }
                        }else if(timeType == DestinationSearchQuery.DRAGON_BOAT_FESTIVAL){
                            if (createTime.getMonth() == 6){
                                destIds.add(template.getDestId());
                            }
                        }else if(timeType == DestinationSearchQuery.MOON_FESTIVAL){
                            if (createTime.getMonth() == 9 || createTime.getMonth() == 10){
                                destIds.add(template.getDestId());
                            }
                        }else if(timeType == DestinationSearchQuery.NATION_DAY){
                            if (createTime.getMonth() == 10){
                                destIds.add(template.getDestId());
                            }
                        }else if(timeType == DestinationSearchQuery.WINTER_VACATION){
                            if (createTime.getMonth() == 1 || createTime.getMonth() == 2){
                                destIds.add(template.getDestId());
                            }
                        }else if (timeType == DestinationSearchQuery.SUMMER_VACATION){
                            if (createTime.getMonth() == 6 || createTime.getMonth() == 7 || createTime.getMonth() == 8){
                                destIds.add(template.getDestId());
                            }
                        }
                    }
                }
            }else{
                destIds.add(template.getDestId());
            }
        }
        if (qo.getDaysType() != -1){
            List<Long> destIdByDaysId = strategyDetailService.getDestIdByDaysId(qo.getDaysType());
            for (Long aLong : destIdByDaysId) {
                for (Long destId : destIds) {
                    if(aLong.equals(destId)){
                        filterDays.add(destId);
                    }
                }
            }
            destIds = filterDays;
        }
        //去除重复的目的地
        for (Long destId : destIds) {
            if(!list.contains(destId)){
                list.add(destId);
            }
        }
        List<DestinationTemplate> dests = destinationTemplateService.queryByIds(list);

        return dests;
    }

    private List<StatisVO> getDestByThemeId(Long themeId){
        List<StatisVO> vos = new ArrayList<>();
        List<StrategyTemplate> templates = repository.findByThemeId(themeId);
        List<String> list = new ArrayList<>();
        //去除重复目的地
        for (StrategyTemplate template : templates) {
            if(!list.contains(template.getDestName())){
                StatisVO statisVO = new StatisVO();
                statisVO.setId(template.getDestId());
                statisVO.setName(template.getDestName());
                vos.add(statisVO);
                list.add(template.getDestName());
            }
        }
        return vos;
    }

    private List<StatisVO> queryStatisVoList(String idField,String nameField,String groupName){
        //先查询出主题ID，主题名字，目的地数量存放在theme中
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);

        sources.add(idSource);
        sources.add(nameSource);

        CompositeAggregationBuilder aggregationBuilder = new CompositeAggregationBuilder(groupName,sources);
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(aggregationBuilder);
        //设置size为0，但spring-data限制了size必须大于等于1
        builder.withPageable(PageRequest.of(0,1));
        builder.withIndices(StrategyTemplate.INDEX_NAME);
        builder.withTypes(StrategyTemplate.TYPE_NAME);
        AggregatedPage<StrategyTemplate> search = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        InternalComposite themeGroup = search.getAggregations().get(groupName);
        List<StatisVO> list = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : themeGroup.getBuckets()) {
            Long id = Long.parseLong(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            Long count = bucket.getDocCount();

            StatisVO statisVO = new StatisVO();
            statisVO.setCount(count);
            statisVO.setId(id);
            statisVO.setName(name);
            list.add(statisVO);
        }
        //排序
        Collections.sort(list, new Comparator<StatisVO>() {
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                Long ret = o2.getCount() - o1.getCount();
                return ret.intValue();
            }
        });
        //取前十个
        if(list.size() > 10){
            list = list.subList(0,10);
        }
        return list;
    }
}
